package com.yinxin.thread;

import java.util.concurrent.LinkedTransferQueue;
import java.util.concurrent.TransferQueue;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.LockSupport;
import java.util.concurrent.locks.ReentrantLock;

/**
 * @author yinxin
 * @version 1.0
 * @Description:
 * @date 2022/5/1113:49
 */
public class PrintNumTest {

    private static Thread t1;
    private static Thread t2;

    public static void main(String[] args) {
        char[] a = "1234567".toCharArray();
        char[] b = "ABCDEFG".toCharArray();
        //threadStart1(a,b);
//        threadStart2(a,b);
        threadStart3(a,b);
//        threadStart4(a, b);
    }

    public static void threadStart1(char[] a, char[] b) {
        t1 = new Thread(() -> {
            for (int i = 0; i < a.length; i++) {
                System.out.print(a[i]);
                LockSupport.unpark(t2);//叫醒t2
                LockSupport.park();//t1(当前线程)阻塞
            }
        }, "t1");
        t2 = new Thread(() -> {
            for (int i = 0; i < b.length; i++) {
                LockSupport.park();//t2阻塞
                System.out.print(b[i]);
                LockSupport.unpark(t1);//唤醒(某一个线程)t1
            }
        }, "t2");
        t1.start();
        t2.start();
    }

    public static void threadStart2(char[] a, char[] b) {

        final Object o = new Object();

        t1 = new Thread(() -> {
            synchronized (o) {
                for (int i = 0; i < a.length; i++) {
                    System.out.print(a[i]);
                    try {
                        o.notify();
                        o.wait();
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
                o.notify();
            }
        }, "t1");
        t2 = new Thread(() -> {
            synchronized (o) {
                for (int i = 0; i < b.length; i++) {
                    System.out.print(b[i]);
                    try {
                        o.notify();
                        o.wait();
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
            }
        }, "t2");
        t1.start();
        t2.start();
    }

    public static void threadStart3(char[] a, char[] b) {
        Lock lock = new ReentrantLock();
        //newCondition要在lock锁中才生效。
        Condition conditionT1 = lock.newCondition();
        Condition conditionT2 = lock.newCondition();
        t1 = new Thread(() -> {
            lock.lock();
            try {
                for (int i = 0; i < a.length; i++) {
                    System.out.print(a[i]);
                    conditionT2.signal();
                    conditionT1.await();
                }
                conditionT2.signal();
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                lock.unlock();
            }

        }, "t1");

        t2 = new Thread(() -> {
            lock.lock();
            try {
                for (int i = 0; i < b.length; i++) {
                    System.out.print(b[i]);
                    conditionT1.signal();
                    conditionT2.await();
                }
                conditionT1.signal();
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                lock.unlock();
            }
        }, "t2");
        t1.start();
        t2.start();
    }

    public static void threadStart4(char[] a, char[] b) {
        //一个存储量为0的队列，一个内容传进去需要取接受它，否则会导致这个队列阻塞
        TransferQueue<Character> queue = new LinkedTransferQueue<>();
        t1 = new Thread(() -> {
            try {
                for (int i = 0; i < a.length; i++) {
                    queue.transfer(a[i]);
                    System.out.print(queue.take());
                }
            }catch (Exception e){
                e.printStackTrace();
            }
        }, "t1");

        t2 = new Thread(() -> {
            try {
                for (int i = 0; i < b.length; i++) {
                    System.out.print(queue.take());
                    queue.transfer(b[i]);
                }
            }catch (Exception e){

            }
        }, "t2");
        t1.start();
        t2.start();
    }
}
